package aiku.numericalcontroloa.Service.EmployeeAttendance.Impl;

import aiku.numericalcontroloa.Base.Utils.BaseEnum;
import aiku.numericalcontroloa.Base.Utils.HttpStatus;
import aiku.numericalcontroloa.Base.Utils.Result;
import aiku.numericalcontroloa.Mapper.DepartmentManagement.DepartmentMapper;
import aiku.numericalcontroloa.Mapper.DepartmentManagement.EmployeeDepartmentMapper;
import aiku.numericalcontroloa.Mapper.EmployeeAttendance.ClockinRuleMapper;
import aiku.numericalcontroloa.Mapper.EmployeeAttendance.HolidaysMapper;
import aiku.numericalcontroloa.Mapper.UserMapper;
import aiku.numericalcontroloa.Model.Dto.EmployeeAttendance.ClockinRuleDto;
import aiku.numericalcontroloa.Model.Dto.EmployeeAttendance.HolidaysDto;
import aiku.numericalcontroloa.Model.Dto.PageSelect;
import aiku.numericalcontroloa.Model.Entity.DepartmentManagement.Department;
import aiku.numericalcontroloa.Model.Entity.DepartmentManagement.EmployeeDepartment;
import aiku.numericalcontroloa.Model.Entity.EmployeeAttendance.ClockinRule;
import aiku.numericalcontroloa.Model.Entity.EmployeeAttendance.ClockinRuleWith;
import aiku.numericalcontroloa.Model.Entity.EmployeeAttendance.Holidays;
import aiku.numericalcontroloa.Model.Entity.User;
import aiku.numericalcontroloa.Model.Vo.EmployeeAttendance.ClockinRuleVo;
import aiku.numericalcontroloa.Model.Vo.EmployeeAttendance.HolidaysVo;
import aiku.numericalcontroloa.Service.EmployeeAttendance.ClockinRuleService;
import aiku.numericalcontroloa.common.utils.DateUtils;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Year;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author 黄广庭
 * @Date 2024/2/29 17:41
 */
@Service
public class ClockinRuleServiceImpl implements ClockinRuleService {
    private final ClockinRuleMapper clockinRuleMapper;
    private final EmployeeDepartmentMapper employeeDepartmentMapper;
    private final DepartmentMapper departmentMapper;
    private final UserMapper userMapper;
    private final HolidaysMapper holidaysMapper;

    public ClockinRuleServiceImpl(ClockinRuleMapper clockinRuleMapper, EmployeeDepartmentMapper employeeDepartmentMapper, DepartmentMapper departmentMapper, UserMapper userMapper, HolidaysMapper holidaysMapper) {
        this.clockinRuleMapper = clockinRuleMapper;
        this.employeeDepartmentMapper = employeeDepartmentMapper;
        this.departmentMapper = departmentMapper;
        this.userMapper = userMapper;
        this.holidaysMapper = holidaysMapper;
    }


    @Override
    public Result getClockinRule(ClockinRuleDto clockinRuleDto) {
        if (clockinRuleDto == null || clockinRuleDto.getEmployeeId() == null){
            // 为空默认查询登录用户的打卡规则
            clockinRuleDto = new ClockinRuleDto();
            clockinRuleDto.setEmployeeId(StpUtil.getLoginIdAsString());
        }
        // 查询个人打卡规则
        LambdaQueryWrapper<ClockinRule> clockinRuleLQW = new LambdaQueryWrapper<>();
        clockinRuleLQW.eq(ClockinRule::getEmployeeId,clockinRuleDto.getEmployeeId())
                .eq(ClockinRule::getRuleType,0);
        ClockinRule clockinRule = clockinRuleMapper.selectOne(clockinRuleLQW);
        if (clockinRule == null) {
            // 个人打卡规则为空，查员工部门表
            LambdaQueryWrapper<EmployeeDepartment> employeeDepartmentLQW = new LambdaQueryWrapper<>();
            employeeDepartmentLQW.eq(EmployeeDepartment::getEmployeeId,clockinRuleDto.getEmployeeId());
            List<EmployeeDepartment> employeeDepartmentList = employeeDepartmentMapper.selectList(employeeDepartmentLQW);
            if (employeeDepartmentList.isEmpty()){
                // 员工部门表为空
                String msg = "请联系管理员分配部门，或者设置个人打卡规则";
                return new Result(HttpStatus.NO_CONTENT,msg);
            }else if(employeeDepartmentList.size() == 1){
                // 查询该部门的打卡规则
                clockinRuleLQW = new LambdaQueryWrapper<>();
                EmployeeDepartment employeeDepartment = employeeDepartmentList.get(0);
                clockinRuleLQW.eq(ClockinRule::getDepartmentId,employeeDepartment.getDepartmentId());
                clockinRule = clockinRuleMapper.selectOne(clockinRuleLQW);
                if (clockinRule == null){
                    // 部门打卡规则为空
                    String msg = "请联系管理员设置部门打卡规则，或者设置个人打卡规则";
                    return new Result(HttpStatus.NO_CONTENT,msg);
                }
            }else {
                String msg = "加入了多个部门，请联系管理员设置个人打卡规则";
                return new Result(HttpStatus.NO_CONTENT,msg);
            }
        }
        ClockinRuleVo clockinRuleVo = new ClockinRuleVo();
        BeanUtils.copyProperties(clockinRule,clockinRuleVo);
        // 如果是部门打卡规则
        if (clockinRule.getRuleType() == 1){
            Department department = departmentMapper.selectByIdForDelete(clockinRule.getDepartmentId());
            clockinRuleVo.setName(department.getName());
        }

        // 时间处理
        clockinRuleVo.setForenoonCheckinTime(clockinRule.getForenoonCheckinTime().toString());
        clockinRuleVo.setForenoonCheckoutTime(clockinRule.getForenoonCheckoutTime().toString());
        clockinRuleVo.setAfternoonCheckinTime(clockinRule.getAfternoonCheckinTime().toString());
        clockinRuleVo.setAfternoonCheckoutTime(clockinRule.getAfternoonCheckoutTime().toString());
        // 处理打卡位置
        if(clockinRule.getClockinPosition() != null){
            List<BigDecimal[]> clockinPositionList = new ArrayList<>();
            String[] clockinPositions = clockinRule.getClockinPosition().split(";");
            for (String item : clockinPositions){
                clockinPositionList.add(getClockinPositionList(item));
            }
            clockinRuleVo.setCoordinate(clockinPositionList);
        }
        return Result.success("查询成功",clockinRuleVo);
    }

    @Override
    public Result getClockinRuleList(ClockinRuleDto clockinRuleDto) {
        if (clockinRuleDto == null || clockinRuleDto.getRuleType() == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(clockinRuleDto is null)");
        }
        if (clockinRuleDto.getCurrentPage() == null || clockinRuleDto.getPageSize() == null){
            return new Result(HttpStatus.BAD_REQUEST,"缺少分页参数");
        }
        List<ClockinRuleVo> clockinRuleVoList = new ArrayList<>();
        long total;
        PageSelect pageSelect = new PageSelect();
        pageSelect.setCurrentPage(clockinRuleDto.getCurrentPage());
        pageSelect.setPageSize(clockinRuleDto.getPageSize());
        pageSelect.setOffset((clockinRuleDto.getCurrentPage()*clockinRuleDto.getPageSize())-clockinRuleDto.getPageSize());
        List<ClockinRuleWith> clockinRuleWithList = new ArrayList<>();
        if (clockinRuleDto.getRuleType().equals(1)){
            // 查部门打卡规则
            clockinRuleWithList = clockinRuleMapper.selectPageWithDepartment(pageSelect, null);
//            System.out.println("部门打卡规则==>"+clockinRuleWithList);
            // 查询总记录
            List<Department> departmentList = departmentMapper.selectList(null);
            total = departmentList.size();
        }else{
            // 查个人打卡规则
            LambdaQueryWrapper<User> userLQW = new LambdaQueryWrapper<>();
            userLQW.eq(User::getState,BaseEnum.USER_INCUMBENCY.getCodeInt());
            if (clockinRuleDto.getEmployeeId() != null && !clockinRuleDto.getEmployeeId().isEmpty()){
                userLQW.and(uLQW ->uLQW.like(User::getNickName,clockinRuleDto.getEmployeeId())
                        .or()
                        .like(User::getPhone,clockinRuleDto.getEmployeeId()));
            }
            Page<User> userPage = new Page<>(clockinRuleDto.getCurrentPage(),clockinRuleDto.getPageSize());
            List<User> userList = userMapper.selectPage(userPage,userLQW).getRecords();
            total = userPage.getTotal();
            // 根据userId查询打卡规则表
            List<String> userIdList = userList.stream().map(User::getId).collect(Collectors.toList());
            if (userList.isEmpty()){
                userIdList.add("");
            }
            LambdaQueryWrapper<ClockinRule> clockinRuleLQW = new LambdaQueryWrapper<>();
            clockinRuleLQW.in(ClockinRule::getEmployeeId,userIdList);
            List<ClockinRule> clockinRuleList = clockinRuleMapper.selectList(clockinRuleLQW);
            // 处理成map，根据userId获取打卡规则
            Map<String,ClockinRule> clockinRuleMap = clockinRuleList.stream().collect(Collectors.toMap(ClockinRule::getEmployeeId,c ->clockinRuleList.stream()
                    .filter(clockinRule -> clockinRule.getEmployeeId().equals(c.getEmployeeId()))
                    .findFirst()
                    .orElse(null)));
            // 处理成ClockinRuleWith
            for (User user : userList){
                ClockinRuleWith clockinRuleWith = new ClockinRuleWith();
                if (clockinRuleMap.containsKey(user.getId())){
                    // 有打卡规则
                    ClockinRule clockinRule = clockinRuleMap.get(user.getId());
                    BeanUtils.copyProperties(clockinRule,clockinRuleWith);
                    clockinRuleWith.setNickName(user.getNickName());
                }else {
                    // 无打卡规则
                    clockinRuleWith.setEmployeeId(user.getId());
                    clockinRuleWith.setNickName(user.getNickName());
                    clockinRuleWith.setDeleted(0);
                }
                clockinRuleWithList.add(clockinRuleWith);
            }
        }
        for (ClockinRuleWith clockinRuleWith : clockinRuleWithList){
            // delete为1，跳过已删除
            if (BaseEnum.DELETED_YES.getCodeInt().equals(clockinRuleWith.getDeleted())){
                continue;
            }
            ClockinRuleVo clockinRuleVo = new ClockinRuleVo();
            BeanUtils.copyProperties(clockinRuleWith,clockinRuleVo);

            // 处理时间格式
            // 上午签到
            if (clockinRuleWith.getForenoonCheckinTime() != null){
                clockinRuleVo.setForenoonCheckinTime(DateUtils.HMSFormat(clockinRuleWith.getForenoonCheckinTime().toString()));
            }
            // 上午签退
            if (clockinRuleWith.getForenoonCheckoutTime() != null){
                clockinRuleVo.setForenoonCheckoutTime(DateUtils.HMSFormat(clockinRuleWith.getForenoonCheckoutTime().toString()));
            }
            // 下午签到
            if (clockinRuleWith.getAfternoonCheckinTime() != null){
                clockinRuleVo.setAfternoonCheckinTime(DateUtils.HMSFormat(clockinRuleWith.getAfternoonCheckinTime().toString()));
            }
            // 下午签退
            if (clockinRuleWith.getAfternoonCheckoutTime() != null){
                clockinRuleVo.setAfternoonCheckoutTime(DateUtils.HMSFormat(clockinRuleWith.getAfternoonCheckoutTime().toString()));
            }

            // 处理打卡位置
            if(clockinRuleWith.getClockinPosition() != null){
                List<BigDecimal[]> clockinPositionList = new ArrayList<>();
                String[] clockinPositions = clockinRuleWith.getClockinPosition().split(";");
                for (String item : clockinPositions){
                    clockinPositionList.add(getClockinPositionList(item));
                }
                clockinRuleVo.setCoordinate(clockinPositionList);
            }
            // 设置规则类型
            clockinRuleVo.setRuleType(clockinRuleDto.getRuleType());
            clockinRuleVoList.add(clockinRuleVo);
        }
        Map<String,Object> map = new HashMap<>();
        map.put("total",total);
        map.put("clockinRuleVoList",clockinRuleVoList);
        return Result.success("查询成功",map);
    }

    @Override
    public Result updateClockinRule(ClockinRuleDto clockinRuleDto) {
        if (clockinRuleDto == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(clockinRuleDto is null)");
        }
        ClockinRule clockinRule = new ClockinRule();
        BeanUtils.copyProperties(clockinRuleDto,clockinRule);

//        System.out.println("clockinRule==>"+clockinRule);
        // 判断是否有id,有则是修改，没有则是新增
        if(clockinRule.getId() != null){
            // 修改
            clockinRuleMapper.deleteById(clockinRule);
            clockinRule.setId(null);
            clockinRuleMapper.insert(clockinRule);
        }else {
            // 新增
            clockinRuleMapper.insert(clockinRule);
        }
        return Result.success("操作成功");
    }

    @Override
    public Result getHolidays() {
        List<Holidays> holidaysList = holidaysMapper.selectList(null);
        List<HolidaysVo> holidaysVoList = new ArrayList<>();
        for (Holidays holidays : holidaysList){
            HolidaysVo holidaysVo = new HolidaysVo();
            holidaysVo.setId(holidays.getId());
            holidaysVo.setYearValue(holidays.getYearValue());
            // 处理时间
            List<String> dateList = new ArrayList<>();
            String[] split = holidays.getDates().split(";");
            for (String item : split){
                dateList.add(DateUtils.YMDFormatDateString(item));
            }
            holidaysVo.setDates(dateList);
            holidaysVoList.add(holidaysVo);
        }
        return Result.success("查询成功",holidaysVoList);
    }

    @Override
    public Result resetClockinRule(ClockinRuleDto clockinRuleDto) {
        if (clockinRuleDto == null || clockinRuleDto.getId() == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(clockinRuleDto is null)");
        }
        // 先查询该规则
        ClockinRule oldRule = clockinRuleMapper.selectById(clockinRuleDto.getId());
        if (oldRule == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数错误(该打卡规则不存在)");
        }
        clockinRuleMapper.deleteById(clockinRuleDto.getId());
        return Result.success("重置成功");
    }

    @Override
    public Result addHolidays(HolidaysDto holidaysDto) {
        if (holidaysDto == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(holidaysDto is null)");
        }
        // 先查询是否有相同的年份
//        List<Year> yearList = holidaysMapper.selectList(null)
//                .stream().map(Holidays::getYearValue).collect(Collectors.toList());
//        for (Year year : yearList){
//            if (year.equals(holidaysDto.getYearValue())){
//                return new Result(HttpStatus.SUCCESS,"重复的参数");
//            }
//        }
        // 查询是否有相同的年份
        LambdaQueryWrapper<Holidays> holidaysLQW = new LambdaQueryWrapper<>();
        holidaysLQW.eq(Holidays::getYearValue,holidaysDto.getYearValue());
        Holidays holidays1 = holidaysMapper.selectOne(holidaysLQW);
        if (holidays1 != null){
            return new Result(HttpStatus.BAD_REQUEST,"已有该年份节假日记录");
        }
        Holidays holidays = new Holidays();
        holidays.setYearValue(holidaysDto.getYearValue());
        StringBuilder dateString = new StringBuilder();
        for (int i = 0; i < holidaysDto.getDates().size(); i++) {
            if (i == holidaysDto.getDates().size() -1){
                dateString.append(DateUtils.dateStringFormatYMD(holidaysDto.getDates().get(i).toString()));
            }else {
                dateString.append(DateUtils.dateStringFormatYMD(holidaysDto.getDates().get(i).toString())).append(";");
            }
        }
        //System.out.println("dateString===>"+dateString);
        holidays.setDates(String.valueOf(dateString));
        holidaysMapper.insert(holidays);
        return Result.success("添加成功");
    }

    @Override
    public Result updateHolidays(HolidaysDto holidaysDto) {
        if (holidaysDto == null || holidaysDto.getDates() == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(holidaysDto is null)");
        }
        Holidays holidays = new Holidays();
        holidays.setId(holidaysDto.getId());
        holidays.setYearValue(holidaysDto.getYearValue());
        StringBuilder dateString = new StringBuilder();
        for (int i = 0; i < holidaysDto.getDates().size(); i++) {
            if (i == holidaysDto.getDates().size() -1){
                dateString.append(DateUtils.dateStringFormatYMD(holidaysDto.getDates().get(i).toString()));
            }else {
                dateString.append(DateUtils.dateStringFormatYMD(holidaysDto.getDates().get(i).toString())).append(";");
            }
        }
        //System.out.println("dateString===>"+dateString);
        holidays.setDates(String.valueOf(dateString));
        holidaysMapper.updateById(holidays);
        return Result.success("修改成功");
    }

    @Override
    public Result deleteHolidays(HolidaysDto holidaysDto) {
        if(holidaysDto == null || holidaysDto.getId() == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(holidaysDto is null)");
        }
        holidaysMapper.deleteById(holidaysDto.getId());
        return Result.success("删除成功");
    }

    @Override
    public Result getHoliday(HolidaysDto holidaysDto) {
        if (holidaysDto == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(holidaysDto is null)");
        }
        if (holidaysDto.getYearValue() == null){
            return new Result(HttpStatus.BAD_REQUEST,"参数为空(holidaysDto[yearValue] is null)");
        }
        LambdaQueryWrapper<Holidays> holidaysLQW = new LambdaQueryWrapper<>();
        holidaysLQW.eq(Holidays::getYearValue,holidaysDto.getYearValue());
        Holidays holidays = holidaysMapper.selectOne(holidaysLQW);
        HolidaysVo holidaysVo = new HolidaysVo();
        holidaysVo.setId(holidays.getId());
        holidaysVo.setYearValue(holidays.getYearValue());
        // 处理时间
        List<String> dateList = new ArrayList<>();
        String[] split = holidays.getDates().split(";");
        for (String item : split){
            dateList.add(DateUtils.YMDFormatDateString(item));
        }
        holidaysVo.setDates(dateList);
        return Result.success("查询成功",holidaysVo);
    }

    @Override
    public Result isHoliday() {
        // 查询假期表，获取节假日
        LambdaQueryWrapper<Holidays> holidaysLQW = new LambdaQueryWrapper<>();
        holidaysLQW.eq(Holidays::getYearValue, Year.now());
        Holidays holidays = holidaysMapper.selectOne(holidaysLQW);
        HolidaysVo holidaysVo = new HolidaysVo();
        if (holidays == null){
            // 没有节假日，返回true
            holidaysVo.setIsHoliday("true");
            return Result.success("查询成功",holidaysVo);
        }
        // 判断今天是否是假期
        String[] DateList = holidays.getDates().split(";");
        for (String date: DateList) {
            LocalDate localDate = LocalDate.parse(date);
            if (localDate.compareTo(LocalDate.now()) == 0){
                // 为节假日，返回true
                holidaysVo.setIsHoliday("true");
                return Result.success("查询成功",holidaysVo);
            }
        }
        // 不为节假日，返回false
        holidaysVo.setIsHoliday("false");
        return Result.success("查询成功",holidaysVo);
    }

    /**
     * 将字符串经纬度处理成数组
     * @param stringCoordinate
     * @return
     */
    @Override
    public BigDecimal[] getClockinPositionList(String stringCoordinate){
        BigDecimal[] coordinate = new BigDecimal[2];
        String[] coordinates = stringCoordinate.split(",");
        for (int i = 0; i < coordinates.length; i++) {
            coordinate[i] = new BigDecimal(coordinates[i]);
        }
        return coordinate;
    }

    /**
     * 递归获取部门打卡规则
     * @param departmentId 部门id
     * @return 打卡规则对象
     */
    @Override
    public ClockinRule getDepartmentClockinRule(String departmentId){
        LambdaQueryWrapper<ClockinRule> clockinRuleLQW = new LambdaQueryWrapper<>();
        clockinRuleLQW.eq(ClockinRule::getDepartmentId,departmentId)
                .eq(ClockinRule::getRuleType,1);
        ClockinRule clockinRule = clockinRuleMapper.selectOne(clockinRuleLQW);
        if (clockinRule != null && clockinRule.getForenoonCheckinTime() != null){
            return clockinRule;
        }
        Department department = departmentMapper.selectById(departmentId);
        if (department.getParentDepartmentId() == null){
            return null;
        }else{
            return getDepartmentClockinRule(department.getParentDepartmentId());
        }
    }
}
